#include<iostream>
#include<stdio.h>
#include<string>
#include<cstring>
#include<stdlib.h>
#include<unistd.h>
#include<sys/wait.h>
using namespace std;

const int basesize = 1024;
const int csize = 64;
const int size = 64;
char* genv[size];
char* gargv[csize];
char pwdenv[size];


string GetUserName()
{
	string name = getenv("USER");
	return name.empty() ? 	"None": name;
}

string GetHostName()
{
	string hostname = strtok(getenv("HOSTNAME"), ".");
	return hostname.empty() ?   "None": hostname;
}

string GetPwd()
{
	char pwd[basesize];
	if(getcwd(pwd, basesize) == nullptr) return "None";
	snprintf(pwdenv, sizeof(pwdenv), "PWD=%s", pwd);
	putenv(pwdenv);
	//printf("%s\n", getenv("PWD"));

	return pwd;
	//string pwd = getenv("PWD");
	//return pwd.empty() ?   "None": pwd;
} 

void PrintCommandLine()
{
	printf("[%s@%s %s]& ", GetUserName().c_str(), GetHostName().c_str(), GetPwd().c_str());
	fflush(stdout);
}

bool GetCommandLine(char commandline[])
{
	char* str = fgets(commandline, basesize, stdin);
	if(str)
	{
		commandline[strlen(commandline)-1] = 0;//将命令行最后\n更改为\0避免exec操作失败
		return true;
	}
	return false;
}

void debug(char commandline[])
{
	printf("%s", commandline);
}

void ParseCommandLine(char commandline[], int size)
{
	(void)size;
	memset(gargv, 0, sizeof(gargv));
	int gargc = 0;
	gargv[gargc++] = strtok(commandline, " ");
	while((bool)(gargv[gargc++] =strtok(nullptr, " ")));
}

bool ExecuteCommandLine()
{
	pid_t i = fork();
	if(i < 0){printf("cuowu ");return false;}
	else if(i == 0 )
	{
		execvp(gargv[0], gargv);
		exit(1);
	}
	int status = 0;
	pid_t rid = waitpid(i, &status, 0);
	if(rid > 0)
	{
		return true;
	}
	return false;
}

bool BuiltCommandLine()
{
	if(strcmp(gargv[0], "cd")==0)
	{
		if(gargv[1] != nullptr)
		{
			if(chdir(gargv[1]) == -1)
			printf("%s\n",strerror(errno));
			
		}
		return true;
	}
	else if(strcmp(gargv[0], "env") == 0)
	{
	        for(int i = 0; environ[i]; i++)
        	{
			if(strcmp(genv[i],environ[i]) != 0)
			{
				free(genv[i]);
				genv[i] = (char*)malloc(strlen(environ[i]) + 1);
                		strncpy(genv[i], environ[i], strlen(environ[i]));
			} 
			printf("%s\n", genv[i]);
        	}
		//printf("zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz");
		return true;
	}
	return false;
}

void InitEnv()
{
	extern char** environ;
	int i = 0;
	for(; environ[i]; i++)
	{
		genv[i] = (char*)malloc(strlen(environ[i]) + 1);
		strncpy(genv[i], environ[i], strlen(environ[i]));
	}
	genv[i] = nullptr;
}

int main()
{
	InitEnv();
	char commandline[basesize];
	while(true)
	{
		PrintCommandLine();//打印命令行提示符
		//sleep(1);
		if(!GetCommandLine(commandline))//得到用户命令
		{
			continue;
		}
		//debug(commandline);
		ParseCommandLine(commandline, basesize);//分析命令
		if(BuiltCommandLine()) 
		{
			continue;
		}
		ExecuteCommandLine();//执行命令
	}
}

